.spPoints <- function(df){
  pnts <- df@coords
  data <- df@data
  ## coords 2 geopoint
  pnt.count <- nrow(pnts)
  
  result.geos <- lapply(c(1:pnt.count), function(i){
     geo <- CreatePoint(pnts[i,1],pnts[i,2])
     return(geo@pointer)
  })
  #result.geos <- vector("list", pnt.count)
  #for(i in c(1:pnt.count)){
  #  geo <- CreatePoint(pnts[i,1],pnts[i,2])
  #  result.geos[i] <- list(geo@pointer)
  #}
  field.names <- names(data)
  field.values <- .data2fields(data)
  return(list(result.geos, field.names, field.values))
}

.spLines <- function(df){
  splines <- as.SpatialLines.SLDF(df)
  geos <- Sp2Geometry(splines)
  field.values <- .data2fields(df@data)
  #count <- length(geos)
  result.geos <- lapply(geos, function(geo){
    return(geo@pointer)
  })
  #result.geos <- vector("list", count)
  #for(i in c(1:count)){
  #  result.geos[i] <- list(geos[[i]]@pointer)
  #}
  field.names <- names(df@data)
  return(list(result.geos, field.names, field.values))
}

.spRegions <- function(df){
  spRegion <- as.SpatialPolygons.PolygonsList(df@polygons)
  geos <- Sp2Geometry(spRegion)
  field.values <- .data2fields(df@data)
  #count <- length(geos)
  #result.geos <- vector("list", count)
  #for(i in c(1:count)){
  #  result.geos[i] <- list(geos[[i]]@pointer)
  #}
  result.geos <- lapply(geos, function(geo){
    return(geo@pointer)
  })
  field.names <- names(df@data)
  return(list(result.geos, field.names, field.values))
}

.spData <- function(df){
  field.names <- names(df)
  field.values <- .data2fields(df)
  return(list(list(), field.names, field.values))
}

.data2fields <- function(data){
  record.values <- vector(mode="list", length = nrow(data))
  for(i in c(1:nrow(data))){
    record.values[[i]] <- sapply(data[i,], as.character, USE.NAMES = FALSE)
  }
  return(record.values)
}

WriteSpData <- function(df, ds, name){
  datasetType <- character()
  df.class <- class(df)
  if (df.class == "data.frame") {
    datasetType = "Tabular"
  } else if (df.class == "SpatialPointsDataFrame"){
    datasetType = "Point"
  } else if (df.class == "SpatialLinesDataFrame"){
    datasetType = "Line"
  } else if (df.class == "SpatialPolygonsDataFrame"){
    datasetType = "Region"
  } else {
    stop("unsupported type")
  }
  
  if(is.null(ds) || !is(ds, "Datasource")){
    stop("ds must be Datasource object")
  }
  
  if(is.null(name) || !is.character(name)){
    stop("name must be valid dataset name")
  }
  
  records <- NULL
  if (df.class == "data.frame") {
    records <- .spData(df)
  } else if (df.class == "SpatialPointsDataFrame"){
    records <- .spPoints(df)
  } else if (df.class == "SpatialLinesDataFrame"){
    records <- .spLines(df)
  } else if (df.class == "SpatialPolygonsDataFrame"){
    records <- .spRegions(df)
  } else {
    stop("unsupported sp type")
  }
  
  geos <- records[[1]]
  field.Names <- records[[2]]
  field.values <- records[[3]]
  res <- .iCall("R_DatasetVector_write", geos, field.Names, field.values, ds@pointer, name, datasetType, PACKAGE="RSuperMap")
  
  if (is.null(res) || is.logical(res)) {
    warning("Adding records to dataset failed")
    return(FALSE)
  } else {
    dtName = GetDatasetName(res)
    ds@datasets[dtName] <- list(res)
    alias <- GetAlias(ds)
    .SetDatasource(alias, ds)
    return(list(ds, res))
  }
}

AppendSpData <- function(df, dtv){
  datasetType <- character()
  df.class <- class(df)
  if(df.class == "data.frame") {
    datasetType = "Tabular"
  } else if(df.class == "SpatialPointsDataFrame") {
    datasetType = "Point"
  } else if(df.class == "SpatialLinesDataFrame") {
    datasetType = "Line"
  } else if(df.class == "SpatialPolygonsDataFrame") {
    datasetType = "Region"
  } else {
    stop("unsupported type")
  }
  if(is.null(dtv) || !is(dtv, "DatasetVector")){
    stop("dtv must be DatasetVector object")
  }

  dtvtype <- GetDatasetType(dtv)
  if (datasetType != dtvtype) {
    stop("dataset type mismatch")
  }
  
  records <- NULL
  if (df.class == "data.frame") {
    records <- .spData(df)
  } else if(df.class == "SpatialPointsDataFrame") {
    records <- .spPoints(df)
  } else if(df.class == "SpatialLinesDataFrame") {
    records <- .spLines(df)
  } else if(df.class == "SpatialPolygonsDataFrame") {
    records <- .spRegions(df)
  }
  
  geos <- records[[1]]
  field.Names <- records[[2]]
  field.values <- records[[3]]
  res <- .iCall("R_DatasetVector_append", geos, field.Names, field.values, dtv@pointer, PACKAGE="RSuperMap")
  
  if (is.null(res)) {
    warning("Adding records to dataset failed")
    return(FALSE)
  } else{
    return(res)
  }
}